package com.radar.task.zx784;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.radar.algorithm.DenseLucaskanade;
import com.radar.algorithm.MathCommon;
import com.radar.algorithm.SemiLagrangian;
import com.radar.common.DateConstants;
import com.radar.common.GisConstants;
import com.radar.task.cd.Constants;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.indexer.Indexer;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author: fy-wbj
 * @description: radar task
 * @date: 2021-04-21
 */
@Component
@Slf4j
public class Forecast784Task {

    @Value("${rootPath}")
    private String input;


//    @Scheduled(cron = "0 0/6 * * * ? ")

    /**
     * 覆盖代码注释
     * @throws Exception
     */
    public void forecast784() throws Exception {
        List<File> collect = FileUtil.loopFiles(input).stream().filter(i ->
                Pattern.matches("^(\\d{14})_VOL_(.*?)_GRAY.png$", i.getName())).collect(Collectors.toList());
        for (File file : collect) {
            // 搜索上一个时次
            Optional<File> min = collect.stream()
                    .filter(i -> i.getName().contains(file.getName().substring(14, file.getName().length() - 1)))
                    .filter(i -> !i.getName().substring(0, 14).equals(file.getName().substring(0, 14)))
                    .filter(i -> Long.parseLong(i.getName().substring(0, 14)) - Long.parseLong(file.getName().substring(0, 14)) < 0)
                    .min(Comparator.comparingLong(i -> Math.abs(Long.parseLong(i.getName().substring(0, 14)) - Long.parseLong(file.getName().substring(0, 14)))));
            if (min.isPresent()) {
//                if (FileUtil.exist(file.getAbsolutePath() + ".OK")) {
//                    continue;
//                } else {
//                    FileUtil.touch(file.getAbsolutePath() + ".OK");
//                }
                String outDirFlow = Constants.ncPath + File.separator + file.getName().substring(0, 14) + File.separator;
                long offset = DateUtil.between(
                        DateUtil.parse(min.get().getName().substring(0, 14), DateConstants.DATE_TIME_FORMAT_YYYYMMDDHHMISS),
                        DateUtil.parse(file.getName().substring(0, 14), DateConstants.DATE_TIME_FORMAT_YYYYMMDDHHMISS),
                        DateUnit.MINUTE);
                if (offset < 15) {
                    try {
                        forecastItem(min.get(), file, file, (int) offset, outDirFlow, "RADAR");
                        if (file.getName().contains("_VOL_LAYER_100_GRAY.png")) {
                            String vis = file.getParentFile().getAbsolutePath() + File.separator + file.getName().substring(0, 14) + "_VOL_LAYER_300_VIS.png";
                            if (FileUtil.exist(vis)) {
                                forecastItem(min.get(), file, new File(vis), (int) offset, outDirFlow, "VIS");
                            }
                            String cloud = file.getParentFile().getAbsolutePath() + File.separator + file.getName().substring(0, 14) + "_VOL_LAYER_CLOUD.png";
                            if (FileUtil.exist(cloud)) {
                                forecastItem(min.get(), file, new File(cloud), (int) offset, outDirFlow, "CLOUD");
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 覆盖代码注释
     * @param prefile
     * @param nextImg
     * @param target
     * @param offset
     * @param outDirFlow
     * @param type
     * @throws IOException
     */
    public void forecastItem(File prefile, File nextImg, File target, int offset, String outDirFlow, String type) throws IOException {
        FileUtil.mkdir(outDirFlow);
        Mat ff1 = opencv_imgcodecs.imread(prefile.getAbsolutePath());
        Mat ff2 = opencv_imgcodecs.imread(nextImg.getAbsolutePath());
        Mat prvs = ff1.clone();
        Mat next = ff1.clone();
        opencv_imgproc.cvtColor(ff1, prvs, opencv_imgproc.COLOR_BGR2GRAY);
        opencv_imgproc.cvtColor(ff2, next, opencv_imgproc.COLOR_BGR2GRAY);

        int w = prvs.size().get(0);
        int h = prvs.size().get(1);
        double[][] pre = new double[h][w];
        double[][] nex = new double[h][w];
        Indexer indexer = prvs.createIndexer();
        Indexer indexer1 = next.createIndexer();
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                pre[i][j] = indexer.getDouble(i, j);
                if (pre[i][j] == 0) {
                    pre[i][j] = 255;
                }
                nex[i][j] = indexer1.getDouble(i, j);
                if (nex[i][j] == 0) {
                    nex[i][j] = 255;
                }
            }
        }
        double[][][] cacl = DenseLucaskanade.cacl(new double[][][]{pre, nex});
        double[][] u = cacl[0];
        double[][] v = cacl[1];
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                u[i][j] = u[i][j] * (6.0 / offset);
                v[i][j] = v[i][j] * (6.0 / offset);
            }
        }
        double[][] decode = new double[u.length][u[0].length];
        // tran 灰度图
        BufferedImage read = ImageIO.read(new File(target.getAbsolutePath()));
        if (type.equals("VIS")) {
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    Color color = new Color(read.getRGB(j, i));
                    decode[i][j] = GisConstants.UNDEF;
                    if (color.getRGB() == Color.red.getRGB()) {
                        decode[i][j] = 300;
                    }
                    if (color.getRGB() == Color.yellow.getRGB()) {
                        decode[i][j] = 400;
                    }
                    if (color.getRGB() == Color.blue.getRGB()) {
                        decode[i][j] = 650;
                    }
                    if (color.getRGB() == Color.green.getRGB()) {
                        decode[i][j] = 950;
                    }
                }
            }
        } else if (type.equals("CLOUD")) {
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    Color color = new Color(read.getRGB(j, i));
                    decode[i][j] = GisConstants.UNDEF;
                    if (color.getRGB() == Color.green.getRGB()) {
                        decode[i][j] = 5;
                    } else if (color.getRGB() == Color.yellow.getRGB()) {
                        decode[i][j] = -5;
                    } else if (color.getRGB() == Color.blue.getRGB()) {
                        decode[i][j] = -15;
                    }
                }
            }
        } else {
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    int r = new Color(read.getRGB(j, i)).getRed();
                    if (r == 0) {
                        decode[i][j] = GisConstants.UNDEF;
                    } else {
                        decode[i][j] = -40 + (r) / 255.0 * 60;
                    }
                }
            }
        }
        SemiLagrangian semiLagrangian = new SemiLagrangian();
        int t = 20;
        float[][][] extrapolate = semiLagrangian.extrapolate(MathCommon.doubleToFloat(decode), MathCommon.doubleToFloat(u), MathCommon.doubleToFloat(v), t);
        for (int i = 0; i < t; i++) {
            BufferedImage bufferedImage;
            bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            for (int j = 0; j < u.length; j++) {
                for (int k = 0; k < u[0].length; k++) {
                    if (type.equals("VIS")) {
                        if (extrapolate[i][j][k] == 0 || Float.isNaN(extrapolate[i][j][k])) {
                            bufferedImage.setRGB(k, j, new Color(0, 0, 0, 0).getRGB());
                        } else {
                            Color color = GetColorByVIS(extrapolate[i][j][k]);
                            if (color == null) {
                                bufferedImage.setRGB(k, j, new Color(0, 0, 0, 0).getRGB());
                            } else {
                                bufferedImage.setRGB(k, j, color.getRGB());
                            }
                        }
                    } else if (type.equals("CLOUD")) {
                        if (extrapolate[i][j][k] == 0 || Float.isNaN(extrapolate[i][j][k])) {
                            bufferedImage.setRGB(k, j, new Color(0, 0, 0, 0).getRGB());
                        } else {
                            Color color = GetColorByCLOUD(extrapolate[i][j][k]);
                            if (color == null) {
                                bufferedImage.setRGB(k, j, new Color(0, 0, 0, 0).getRGB());
                            } else {
                                bufferedImage.setRGB(k, j, color.getRGB());
                            }
                        }
                    } else {
                        if (extrapolate[i][j][k] == 0 || Float.isNaN(extrapolate[i][j][k])) {
                            bufferedImage.setRGB(k, j, new Color(0, 0, 0, 0).getRGB());
                        } else if (extrapolate[i][j][k] == 20) {
                            bufferedImage.setRGB(k, j, new Color(232, 38, 38).getRGB());
                        } else {
                            Color color = GetColorByDBZ(extrapolate[i][j][k]);
                            if (color == null) {
                                bufferedImage.setRGB(k, j, new Color(0, 0, 0, 0).getRGB());
                            } else {
                                bufferedImage.setRGB(k, j, color.getRGB());
                            }
                        }
                    }
                }
            }
            ImageIO.write(bufferedImage, "png", new File(outDirFlow + File.separator + target.getName() + "_" + (i + 1) + ".png"));
        }
    }


    /**
     * 覆盖代码注释
     * @param dbz
     * @return
     */
    public static Color GetColorByDBZ(double dbz) {
        Color t_clr = null;
        if (dbz <= -40) {
            t_clr = new Color(0, 0, 0, 0);
        } else if (dbz <= -36) {
            t_clr = new Color(13, 0, 130);
        } else if (dbz <= -32) {
            t_clr = new Color(0, 0, 191);
        } else if (dbz <= -28) {
            t_clr = new Color(2, 54, 232);
        } else if (dbz <= -24) {
            t_clr = new Color(2, 97, 253);
        } else if (dbz <= -20) {
            t_clr = new Color(41, 172, 250);
        } else if (dbz <= -16) {
            t_clr = new Color(13, 220, 237);
        } else if (dbz <= -12) {
            t_clr = new Color(2, 208, 136);
        } else if (dbz <= -8) {
            t_clr = new Color(0, 191, 67);
        } else if (dbz <= -4) {
            t_clr = new Color(113, 203, 46);
        } else if (dbz <= 0) {
            t_clr = new Color(196, 224, 61);
        } else if (dbz <= 4) {
            t_clr = new Color(255, 255, 112);
        } else if (dbz <= 8) {
            t_clr = new Color(248, 205, 118);
        } else if (dbz <= 12) {
            t_clr = new Color(247, 193, 83);
        } else if (dbz <= 16) {
            t_clr = new Color(240, 163, 44);
        } else if (dbz <= 20) {
            t_clr = new Color(234, 111, 46);
        }
        return t_clr;
    }

    /**
     * 覆盖代码注释
     * @param dbz
     * @return
     */
    public static Color GetColorByVIS(double dbz) {
        Color t_clr;
        if (dbz <= 300 && dbz >= 150) {
            t_clr = Color.red;
        } else if (dbz > 300 && dbz < 500) {
            t_clr = Color.yellow;
        } else if (dbz >= 500 && dbz <= 800) {
            t_clr = Color.blue;
        } else if (dbz > 800) {
            t_clr = Color.green;
        } else {
            t_clr = new Color(111, 248, 255, 0);
        }
        return t_clr;
    }

    /**
     * 覆盖代码注释
     * @param dbz
     * @return
     */
    public static Color GetColorByCLOUD(double dbz) {
        Color t_clr;
        if (dbz > 0) {
            t_clr = Color.green;
        } else if (dbz < 0 && dbz > -10) {
            t_clr = Color.yellow;
        } else if (dbz < -10 && dbz > -20) {
            t_clr = Color.blue;
        } else {
            t_clr = new Color(111, 248, 255, 0);
        }
//        if (dbz >= 300 && dbz <= 500) {
//            t_clr = Color.yellow;
//        } else {
//            t_clr = new Color(111, 248, 255, 0);
//        }
        return t_clr;
    }

}
